//
// Created by secon on 2025/1/30.
//

#ifndef INC_31_TEMPLATE_TEMPLATE_H
#define INC_31_TEMPLATE_TEMPLATE_H
#include <iostream>
#include <vector>
#include <list>

template<typename T>
T maxValue(T a, T b){
    return (a > b) ? a : b;
}

template<typename T, typename U>
class Pair{
    public:
        T first;
        U second;
        Pair(T a, U b): first(a), second(b){}
        void print() const{
            std::cout << "Pair: " << first<< ", " << second << std::endl;
        }

    };

template<typename T, typename U>
class Pair<T,U*>{
public:
    T first;
    U* second;
    Pair(T a, U* b): first(a), second(b){}
    void print() const{
        std::cout << "Pair: " << first<< ", " << *second << std::endl;
    }

};


template<typename T, std::size_t N>
class FixedArray{
public:
    T data[N];

    T& operator[](std::size_t index){
        return data[index];
    }

    void print() const{
        for(std::size_t i = 0; i < N; ++i){
            std::cout << data[i] << " ";
        }
        std::cout << std::endl;
    }
};

template<template<typename , typename  > class Container, typename T>
class ContainerPrinter{
public:
    void print(const Container<T, std::allocator<T>> & container){
        for(const auto& elem : container){
            std::cout << elem << " ";
        }

        std::cout << std::endl;
    }
};

template<typename T>
class Printer{
public:
    void print(const T& obj){
        std::cout << "General Printer : " << obj << std::endl;
    }
};

template<>
class Printer<std::string>{
public:
    void print(std::string obj){
        std::cout << "String Printer : " << obj << std::endl;
    }
};

template<typename T>
void printValue(const T& obj){
    std::cout << "General printValue : " << obj << std::endl;
}

template<>
inline void printValue<std::string>(const std::string& value){
    std::cout << "Specialized print for std::string: " << value << std::endl;
}

template<>
void printValue<int*>( int* const& value);

void printAll();
//10,20.5,"abc"
template<typename T, typename... Args>
void printAll(const T& first, const Args&...  args){
    std::cout << first << " ";
    printAll(args...);
}

template<typename... Args>
void coutAll(const Args&... args){
    ((std::cout << args<< " "), ...);
    std::cout << std::endl;
}

template<typename... Args>
auto sumAll(Args... args)-> decltype((args + ...)){
    return (args + ...);
}

//对每个参数非操作，然后再将这些操作&&
//(!args && ...) 相当于 !a && !b && ...
template<typename... Args>
bool allNot(const Args&... args){
    return (!args && ...);
}

template<typename... Args>
auto sumLeftFold(const Args&... args)->decltype((args + ...)){
    return (args + ...);
}

template<typename... Args>
auto multiRightFold(const Args& ... args)->decltype((args * ...)){
    return (... *args);
}

//std::cout << a << b << c;
template<typename... Args>
void printFoldAll(const Args&... args){
    //左折叠
    (std::cout << ... << args) << std::endl;
}

struct MyPoint{
        int x, y;
        MyPoint(int a, int b): x(a), y(b){}
        MyPoint operator + (const MyPoint& other) const{
            return MyPoint(x + other.x, y + other.y);
        }
    };

template<typename... Args>
auto sumPoints(const Args&... args)->decltype((args + ...)){
    return (args + ...);
}

#endif //INC_31_TEMPLATE_TEMPLATE_H
